package com.activiti6.demo.stress;

import com.activiti6.demo.Activiti6DemoApplication;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.activiti.engine.runtime.ProcessInstance;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.time.Duration;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.logging.Logger;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Activiti6DemoApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class StressTest {

    @Autowired
    RuntimeService runtimeService;

    private void testPrint() {
//        new PrintServiceTest().testPrint();
        System.out.println();
        System.out.println(LocalTime.now() + " 开始测试..");
        runtimeService.startProcessInstanceByKey("stressProcess");
        System.out.println(LocalTime.now() + " 测试结束..");
        System.out.println();
    }


    // 并发次数
    private final static int CONCURRENT_TIMES = 10;

    // 线程池设置
    static ExecutorService e = Executors.newCachedThreadPool();
    //static ExecutorService e = Executors.newScheduledThreadPool(1000);// 并发间隔时间，单位毫秒
    //static ExecutorService e = Executors.newFixedThreadPool(10);// 固定线程数
    //static ExecutorService e = Executors.newSingleThreadExecutor();

    @Test
    public void testStressPrint() {
        Logger.getGlobal().info(
                () -> "并发测试开始。" + "并发次数：" + CONCURRENT_TIMES + "次。\n");

        // 开始时间
        LocalTime startTime = LocalTime.now();
        // 完成时间
        LocalTime finishedTime;

//        System.out.println("开始调用：" + startTime);
        for (int i = 0; i < CONCURRENT_TIMES; i++) {
            e.submit(() -> {
                try {
                    testPrint();
                    Thread.yield();
                } catch (Exception ex) {
                    // ex.printStackTrace();
                }
            });
        }

//        System.out.println("调用完成：" + LocalTime.now());
//
//        finishedTime = LocalTime.now();
//        System.out.println("获取结果：" + finishedTime);
//
//        Duration duration = Duration.between(startTime, finishedTime);
//
//        System.out.print("一共并发执行" + CONCURRENT_TIMES + "次：");
//        System.out.println("共耗时" + duration.getSeconds() + "秒" + duration.getNano() / 1000000 + "毫秒。\n");

//        e.shutdown();
    }

    public static void main(String[] args) {
        Logger.getGlobal().info(
                () -> "并发测试开始。" + "并发次数：" + CONCURRENT_TIMES + "次。\n");

        ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
                .setJdbcUrl("jdbc:h2:mem:flowable;DB_CLOSE_DELAY=-1")
                .setJdbcUsername("sa")
                .setJdbcPassword("")
                .setJdbcDriver("org.h2.Driver")
                .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE)
//                .setJdbcMaxActiveConnections(200)
                ;

        ProcessEngine processEngine = cfg.buildProcessEngine();

        RepositoryService repositoryService = processEngine.getRepositoryService();
        repositoryService.createDeployment()
                .addClasspathResource("StressProcess.bpmn")
                .deploy();

        RuntimeService runtimeService = processEngine.getRuntimeService();

        System.out.println(LocalTime.now() + "并发开始。");

        for (int i = 0; i < CONCURRENT_TIMES; i++) {
            e.submit(() -> {
                try {
                    runtimeService.startProcessInstanceByKey("stressProcess");
                    Thread.yield();
                } catch (Exception ex) {
                    // ex.printStackTrace();
                }
            });
        }

        System.out.println(LocalTime.now() + "并发完成");

    }

}
